﻿
Imports std
Imports System.Text

Public Class contextpool_t
    Inherits iContextpool

    Protected Overrides Function create() As context
        Return New context()
    End Function

    Protected Overrides Sub unalloc(ByRef inst As context)
        inst.clear()
        MyBase.unalloc(inst)
    End Sub
End Class

Public Class context
    Implements ICloneable

    <ThreadStatic()> Private Shared threadStaticVariables As variables_t = Nothing
    Private variables As variables_t = Nothing
    Private functions As functions_t = Nothing
#If Not PocketPC AndAlso Not Smartphone Then
    <ThreadStatic()> Protected Shared cp As iContextpool = Nothing
#Else
    Protected Shared cp As iContextpool = Nothing
#End If

    Public Shared Function contextpool() As iContextpool
        If cp Is Nothing Then
            cp = New contextpool_t()
        End If
        Return cp
    End Function

    Shared Sub New()
        initialInternalVariables()
        initialInternalFunctions()
    End Sub

    Public Sub New()
        variables = New variables_t()
        functions = New functions_t()
    End Sub

    Private Shared Sub initialInternalVariables()
        insertSharedVariable("StringStart", New const_bare_variable(typeDefination.string, _
                                                                    Convert.ToString(bare_variable.stringStart)))
        insertSharedVariable("StringEnd", New const_bare_variable(typeDefination.string, _
                                                                  Convert.ToString(bare_variable.stringEnd)))
        insertSharedVariable("quoteMark", New const_bare_variable(typeDefination.string, _
                                                                  Convert.ToString(character.quoteMark)))
        insertSharedVariable("engineName", New const_bare_variable(typeDefination.string, enginename()))
        insertSharedVariable("engineSign", New const_bare_variable(typeDefination.string, enginename()))
        insertSharedVariable("applicationSign", New const_bare_variable(typeDefination.string, applicationSign()))
        insertSharedVariable("predictStart", New const_bare_variable(typeDefination.string, _
                                                                     Convert.ToString(_predict.start)))
        insertSharedVariable("maxInt8", New const_bare_variable(typeDefination.int, convertor.cast(Of Int64)(maxInt8)))
        insertSharedVariable("minInt8", New const_bare_variable(typeDefination.int, convertor.cast(Of Int64)(minInt8)))
        insertSharedVariable("maxUInt8", New const_bare_variable(typeDefination.int, _
                                                                 convertor.cast(Of Int64)(maxUInt8)))
        insertSharedVariable("maxInt16", New const_bare_variable(typeDefination.int, _
                                                                 convertor.cast(Of Int64)(maxInt16)))
        insertSharedVariable("minInt16", New const_bare_variable(typeDefination.int, _
                                                                 convertor.cast(Of Int64)(minInt16)))
        insertSharedVariable("maxUInt16", New const_bare_variable(typeDefination.int, _
                                                                  convertor.cast(Of Int64)(maxUInt16)))
        insertSharedVariable("maxInt32", New const_bare_variable(typeDefination.int, _
                                                                 convertor.cast(Of Int64)(maxInt32)))
        insertSharedVariable("minInt32", New const_bare_variable(typeDefination.int, _
                                                                 convertor.cast(Of Int64)(minInt32)))
        insertSharedVariable("maxUInt32", New const_bare_variable(typeDefination.int, _
                                                                  convertor.cast(Of Int64)(maxUInt32)))
        insertSharedVariable("maxInt64", New const_bare_variable(typeDefination.int, maxInt64))
        insertSharedVariable("minInt64", New const_bare_variable(typeDefination.int, minInt64))
        insertSharedVariable("maxUInt64", New const_bare_variable(typeDefination.var, maxUInt64))
        insertSharedVariable("null", New const_bare_variable(typeDefination.var, Nothing))
        insertSharedVariable("char.newline", New const_bare_variable(typeDefination.string, _
                                                                     Convert.ToString(character.newline)))
        insertSharedVariable("char.return", New const_bare_variable(typeDefination.string, _
                                                                    Convert.ToString(character.return)))
        insertSharedVariable("char.tab", New const_bare_variable(typeDefination.string, _
                                                                 Convert.ToString(character.tab)))
        insertSharedVariable("computername", New const_bare_variable(typeDefination.string, computername()))
        insertSharedVariable("totalPhysicalMemory", New const_bare_variable(typeDefination.var, totalPhysicalMemory()))
        insertSharedVariable("totalVirtualMemory", New const_bare_variable(typeDefination.var, totalVirtualMemory()))
        insertSharedVariable("processorArchitecture", _
                             New const_bare_variable(typeDefination.string, processorArchitecture()))
        insertSharedVariable("osfullname", New const_bare_variable(typeDefination.string, osfullname()))
        insertSharedVariable("osplatform", New const_bare_variable(typeDefination.string, osplatform()))
        insertSharedVariable("osversion", New const_bare_variable(typeDefination.string, osversion()))
        insertSharedVariable("buildinfo", New const_bare_variable(typeDefination.string, buildInfo2))
        insertSharedVariable("npos", New const_bare_variable(typeDefination.int, convertor.cast(Of Int64)(npos)))
        insertSharedVariable("isdebugmode", New const_bare_variable(typeDefination.bool, isdebugmode()))
        insertSharedVariable("isdebugbuild", New const_bare_variable(typeDefination.bool, isdebugbuild()))

        insertErrorHandleSharedVariables()
        insertHttpStatusSharedVariables()
    End Sub

    Private Shared Sub insertErrorHandleSharedVariables()
        Dim i As Int64
        For i = errorHandle.errorType.first + 1 To errorHandle.errorType.last - 1
            insertSharedVariable("ERROR_TYPE_" + errorHandle.errorTypeDefination(i).ToUpper(), _
                                 New const_bare_variable(typeDefination.int, i))
        Next
    End Sub

    Private Shared Sub insertHttpStatusCode(ByVal name As String, ByVal code As Int64)
        insertSharedVariable("HTTP_STATUS_CODE_" + strtoupper(name), New const_bare_variable(typeDefination.int, code))
    End Sub

    Private Shared Sub insertHttpStatusSharedVariables()
        Dim statusCode As Type = Nothing
        statusCode = GetType(Net.HttpStatusCode)
        For Each s In [Enum].GetNames(statusCode)
            insertHttpStatusCode(s, Convert.ToInt32([Enum].Parse(statusCode, s)))
        Next
    End Sub

    Private Shared Sub initialInternalFunctions()
        insertSharedFunction(New internalFunctions._strlen())
        insertSharedFunction(New internalFunctions._strcat())
        insertSharedFunction(New internalFunctions._strcmp())
        insertSharedFunction(New internalFunctions._strmid())
        insertSharedFunction(New internalFunctions._strsepar())
        insertSharedFunction(New internalFunctions._strtolower())
        insertSharedFunction(New internalFunctions._strtoupper())
        insertSharedFunction(New internalFunctions._strindexof())
        insertSharedFunction(New internalFunctions._strlastindexof())
        insertSharedFunction(New internalFunctions._strrplc())
        insertSharedFunction(New internalFunctions.stringformat())

#If Not PocketPC AndAlso Not Smartphone Then
        insertSharedFunction(New internalFunctions.writeConsole())
        insertSharedFunction(New internalFunctions.writeConsoleLine())
        insertSharedFunction(New internalFunctions.readConsole())
        insertSharedFunction(New internalFunctions.consoleCommands())
        insertSharedFunction(New internalFunctions.consoleCommandsMapping())
        insertSharedFunction(New internalFunctions.consoleEnvironments())
        insertSharedFunction(New internalFunctions.consolepause())
        insertSharedFunction(New internalFunctions.exec())
        insertSharedFunction(New internalFunctions.consolereadkey())
#End If

        insertSharedFunction(New internalFunctions.converttobool())
        insertSharedFunction(New internalFunctions.converttofloat())
        insertSharedFunction(New internalFunctions.converttoint())
        insertSharedFunction(New internalFunctions.converttostring())
        insertSharedFunction(New internalFunctions.converttovar())
        insertSharedFunction(New internalFunctions.convertinttostring())
        insertSharedFunction(New internalFunctions.convertstringtoint())
        insertSharedFunction(New internalFunctions.convertinttochar())
        insertSharedFunction(New internalFunctions.convertchartoint())

        insertSharedFunction(New internalFunctions.compare())
        insertSharedFunction(New internalFunctions.less())
        insertSharedFunction(New internalFunctions.equal())

        insertSharedFunction(New internalFunctions.isnull())
        insertSharedFunction(New internalFunctions.notlogic())
        insertSharedFunction(New internalFunctions.andlogic())
        insertSharedFunction(New internalFunctions.orlogic())
        insertSharedFunction(New internalFunctions.ifoperfunc())

        insertSharedFunction(New internalFunctions.increase())
        insertSharedFunction(New internalFunctions.negative())
        insertSharedFunction(New internalFunctions.divide())
        insertSharedFunction(New internalFunctions.divideexactly())
        insertSharedFunction(New internalFunctions.multiply())

        insertSharedFunction(New internalFunctions.stdsizeof())
        insertSharedFunction(New internalFunctions.stdinsert())
        insertSharedFunction(New internalFunctions.stdtake())
        insertSharedFunction(New internalFunctions.stdfind())
        insertSharedFunction(New internalFunctions.stderase())

        insertSharedFunction(New internalFunctions.pntget())
        insertSharedFunction(New internalFunctions.pntset())

        insertSharedFunction(New internalFunctions.rnd())
        insertSharedFunction(New internalFunctions.createGUID())

        insertSharedFunction(New internalFunctions.timelong())
        insertSharedFunction(New internalFunctions.timeshort())
        insertSharedFunction(New internalFunctions.timeticks())
        insertSharedFunction(New internalFunctions.shorttimefromticks())
        insertSharedFunction(New internalFunctions.longtimefromticks())
        insertSharedFunction(New internalFunctions._thisyear())
        insertSharedFunction(New internalFunctions._thismonth())
        insertSharedFunction(New internalFunctions._thisweek())
        insertSharedFunction(New internalFunctions._thisday())
        insertSharedFunction(New internalFunctions._thishour())
        insertSharedFunction(New internalFunctions._thisminute())
        insertSharedFunction(New internalFunctions._thissecond())
        insertSharedFunction(New internalFunctions._thismillisecond())
        insertSharedFunction(New internalFunctions._lastyear())
        insertSharedFunction(New internalFunctions._lastmonth())
        insertSharedFunction(New internalFunctions._lastweek())
        insertSharedFunction(New internalFunctions._lastday())
        insertSharedFunction(New internalFunctions._lasthour())
        insertSharedFunction(New internalFunctions._lastminute())
        insertSharedFunction(New internalFunctions._lastsecond())
        insertSharedFunction(New internalFunctions._lastmillisecond())
        insertSharedFunction(New internalFunctions.yearfromticks())
        insertSharedFunction(New internalFunctions.monthfromticks())
        insertSharedFunction(New internalFunctions.datefromticks())
        insertSharedFunction(New internalFunctions.dayofweekfromticks())
        insertSharedFunction(New internalFunctions.dayofyearfromticks())
        insertSharedFunction(New internalFunctions.hourfromticks())
        insertSharedFunction(New internalFunctions.minutefromticks())
        insertSharedFunction(New internalFunctions.secondfromticks())

        insertSharedFunction(New internalFunctions.multilock_lock())
        insertSharedFunction(New internalFunctions.multilock_release())
        insertSharedFunction(New internalFunctions.threadshare())
        insertSharedFunction(New internalFunctions.threadsleep())

        insertSharedFunction(New internalFunctions.createThreadPool())
        insertSharedFunction(New internalFunctions.threadpoolInsertJob())

        insertSharedFunction(New internalFunctions.readfile())
        insertSharedFunction(New internalFunctions.readfilebytes())
        insertSharedFunction(New internalFunctions.fileexists())
        insertSharedFunction(New internalFunctions.writefile())
        insertSharedFunction(New internalFunctions.appendfile())
        insertSharedFunction(New internalFunctions.copyfile())
        insertSharedFunction(New internalFunctions.listdirectory())
        insertSharedFunction(New internalFunctions.directorycopy())
        insertSharedFunction(New internalFunctions.filedelete())
        insertSharedFunction(New internalFunctions._filename())
        insertSharedFunction(New internalFunctions._parentpath())
        insertSharedFunction(New internalFunctions._filesize())

#If Not PocketPC AndAlso Not Smartphone Then
        insertSharedFunction(New internalFunctions.encodingxml())
        insertSharedFunction(New internalFunctions.decodingxml())
#End If
        insertSharedFunction(New internalFunctions.encodingurl())
        insertSharedFunction(New internalFunctions.decodingurl())

        insertSharedFunction(New internalFunctions.configreader())
        insertSharedFunction(New internalFunctions.configlistreader())

        insertSharedFunction(New internalFunctions._raiseError())

        insertSharedFunction(New internalFunctions.runtimeparse())
        insertSharedFunction(New internalFunctions.runtimeinvoke())
        insertSharedFunction(New internalFunctions._callstack())
        insertSharedFunction(New internalFunctions.elpmisinvoke())
        insertSharedFunction(New internalFunctions.elpmisvar())
        insertSharedFunction(New internalFunctions.hasfunction())
        insertSharedFunction(New internalFunctions.hasvariable())
        insertSharedFunction(New internalFunctions._typeof())
        insertSharedFunction(New internalFunctions.quit())

        insertSharedFunction(New internalFunctions.createalias())

        insertSharedFunction(New internalFunctions.netmethodcall())
        insertSharedFunction(New internalFunctions.netloadclass())
        insertSharedFunction(New internalFunctions.netloadmethodfromclass())
        insertSharedFunction(New internalFunctions.netloadmethod())
        insertSharedFunction(New internalFunctions.netinvoke())

        insertSharedFunction(New internalFunctions.md5_encoding())
        insertSharedFunction(New internalFunctions.sha1_encoding())
        insertSharedFunction(New internalFunctions.sha256_encoding())
        insertSharedFunction(New internalFunctions.sha384_encoding())
        insertSharedFunction(New internalFunctions.sha512_encoding())

        insertSharedFunction(New internalFunctions._availablePhysicalMemory())
        insertSharedFunction(New internalFunctions._availableVirtualMemory())

        insertSharedFunction(New internalFunctions._assert())

        insertSharedFunction(New internalFunctions.threadstatic_register())
    End Sub

#If Not PocketPC AndAlso Not Smartphone Then
    <ThreadStatic()> Private Shared _currentContext As context = Nothing
    <ThreadStatic()> Private Shared _cs As stack(Of pair(Of [function], sentence)) = Nothing
#Else
    Private Shared _currentContext As context = Nothing
    Private Shared _cs As stack(Of [function]) = Nothing
#End If
    Private _parent As context = Nothing

    Public Shared Function currentContext() As context
        assert(Not _currentContext Is Nothing, "context._currentContext is nothing.")
        Return _currentContext
    End Function

    Public Function parent() As context
        Return _parent
    End Function

    Public Function variables_end() As variables_t.iterator
        Return variables.end()
    End Function

    Public Function functions_end() As functions_t.iterator
        Return functions.end()
    End Function

    Public Shared Function sharedVariables_end() As variables_t.iterator
        Return sharedContext.variables_end()
    End Function

    Public Shared Function sharedFunctions_end() As functions_t.iterator
        Return sharedContext.functions_end()
    End Function

    Private Shared Function insertFunction(ByVal name As String, ByVal func As [function], _
                                           ByVal funcs As functions_t) As functions_t.iterator
        assert(Not funcs Is Nothing, "funcs is nothing.")
        assert(Not func Is Nothing, "func is nothing.")
        Dim it As functions_t.iterator = Nothing
        it = funcs.find(name)
        If it <> funcs.end() Then
            If isdebugmode() Then
                raiseError("duplicate function name detected " + func.name() + ", overwrite.", _
                           errorHandle.errorType.user)
            End If
            With +it
                copy(.second, func)
            End With
        Else
            it = funcs.insert(name, func)
        End If

        Return it
    End Function

    Private Shared Function insertFunction(ByVal func As [function], ByVal funcs As functions_t) As functions_t.iterator
        If isdebugbuild() Then
            raiseError("function " + Convert.ToString(func))
        End If
        Dim i As Int64
        For i = 0 To func.aliases().size() - 1
            insertFunction(func.aliases()(i), func, funcs)
        Next
        Return insertFunction(func.name(), func, funcs)
    End Function

    Public Function insertFunction(ByVal f As [function]) As functions_t.iterator
        Return insertFunction(f, functions)
    End Function

    Public Shared Function insertSharedFunction(ByVal func As [function]) As functions_t.iterator
        Return sharedContext.insertFunction(func)
    End Function

    Protected Shared Function insertVariable(Of VT As bare_variable) _
                                            (ByVal name As String, _
                                             ByVal value As VT, _
                                             ByVal vars As variables_t) As  _
                                            variables_t.iterator
        assert(Not vars Is Nothing, "vars is nothing.")
        If isdebugbuild() Then
            raiseError("variable " + name + character.equalSign + Convert.ToString(value))
        End If
        Return vars.insert(name, value)
    End Function

    Public Overridable Function insertVariable(ByVal name As String, ByVal bv As bare_variable) As variables_t.iterator
        Return insertVariable(name, bv, variables)
    End Function

    Public Shared Function insertSharedVariable(ByVal name As String, _
                                                ByVal value As bare_variable) As variables_t.iterator
        Return sharedContext.insertVariable(name, value)
    End Function

    Protected Shared Function findVariable(ByVal name As String, _
                                           ByRef o As bare_variable, _
                                           ByVal vs As variables_t) As Boolean
        assert(Not vs Is Nothing, "vs is nothing.")
        Dim it As variables_t.iterator = Nothing
        it = vs.find(name)
        If it = vs.end() Then
            Return False
        Else
            o = (+it).second
            Return True
        End If
    End Function

    Public Shared Function insertThreadStaticVariable(ByVal name As String, _
                                                      ByVal v As bare_variable) As variables_t.iterator
        If threadStaticVariables Is Nothing Then
            threadStaticVariables = New variables_t()
        End If
        Return insertVariable(name, v, threadStaticVariables)
    End Function

    Public Shared Function insertThreadStaticVariable(ByVal name As String, _
                                                      ByVal type As typeDefination, _
                                                      ByVal value As Object) As variables_t.iterator
        Return insertThreadStaticVariable(name, New bare_variable(type, value))
    End Function

    Public Shared Function threadStaticVariables_end() As variables_t.iterator
        If threadStaticVariables Is Nothing Then
            threadStaticVariables = New variables_t()
        End If
        Return threadStaticVariables.end()
    End Function

    Private Shared Function findThreadStaticVariable(ByVal name As String, ByRef o As bare_variable) As Boolean
        Return Not threadStaticVariables Is Nothing AndAlso findVariable(name, o, threadStaticVariables)
    End Function

    Protected Shared Function findSharedVariable(ByVal name As String, ByRef o As bare_variable) As Boolean
        Return sharedContext.findVariable(name, o)
    End Function

    Protected Function findContextVariable(ByVal name As String, ByRef o As bare_variable) As Boolean
        Return findVariable(name, o, variables)
    End Function

    Public Overridable Function findVariable(ByVal name As String, ByRef o As bare_variable) As Boolean
        Return findContextVariable(name, o) OrElse findSharedVariable(name, o) OrElse findThreadStaticVariable(name, o)
    End Function

    Public Function findVariable(ByVal name As String) As bare_variable
        Return bare_variable_finder().find(Me, name)
    End Function

    Public Function findVariableStr(ByVal name As String, ByRef str As String) As Boolean
        Return string_finder().find(Me, name, str)
    End Function

    Public Function findVariableStr(ByVal name As String) As String
        Return string_finder().find(Me, name)
    End Function

    Public Function findVariableInt(ByVal name As String, ByRef o As Int64) As Boolean
        Return int_finder().find(Me, name, o)
    End Function

    Public Function findVariableInt(ByVal name As String) As Int64
        Return int_finder().find(Me, name)
    End Function

    Public Function findVariableFloat(ByVal name As String, ByRef o As Double) As Boolean
        Return float_finder().find(Me, name, o)
    End Function

    Public Function findVariableFloat(ByVal name As String) As Double
        Return float_finder().find(Me, name)
    End Function

    Public Function findVariableBool(ByVal name As String, ByRef o As Boolean) As Boolean
        Return bool_finder().find(Me, name, o)
    End Function

    Public Function findVariableBool(ByVal name As String) As Boolean
        Return bool_finder().find(Me, name)
    End Function

    Public Function findVariable(Of T)(ByVal name As String, ByRef o As T) As Boolean
        Return t_finder(Of T).find_s(Me, name, o)
    End Function

    Public Function findVariable(Of T)(ByVal name As String) As T
        Return t_finder(Of T).find_s(Me, name)
    End Function

    Public Delegate Function findVariablesCallback(Of T)(ByVal name As String, ByVal var As T, _
                                                         ByRef obj As Object) As Boolean
    Public Delegate Function findVariableDelegate(Of T)(ByVal name As String, ByRef rtn As T) As Boolean

    Private Shared Function findVariablesImpl(Of T)(ByVal func As findVariablesCallback(Of T), _
                                                    ByVal name As String, ByVal var As T, _
                                                    ByRef obj As Object) As Boolean
        Dim rtn As Boolean = False
        Try
            rtn = func(name, var, obj)
        Catch ex As Exception
            raiseError("caught exception when invoke func when iterate to " + name + _
                       ", ex " + ex.Message + ", call stack " + ex.StackTrace, _
                       errorHandle.errorType.critical)
            Return False
        End Try

        If Not rtn Then
            raiseError("cannot invoke func when iterate to " + name, _
                       errorHandle.errorType.exclamation)
        End If
        Return rtn
    End Function

    Private Function findVariables(Of T)(ByVal func As findVariablesCallback(Of T), _
                                         ByVal findVariable As findVariableDelegate(Of T), _
                                         ByVal finder As iVariableFinder(Of T), _
                                         Optional ByVal base As String = Nothing, _
                                         Optional ByVal start As Int64 = 0, _
                                         Optional ByRef obj As Object = Nothing) As Boolean
        If debugassert(Not func Is Nothing, "func is nothing.") AndAlso _
           debugassert(Not findVariable Is Nothing OrElse Not finder Is Nothing, _
                       "findVariable and finder are all nothing.") Then
            Dim i As Int64
            i = start
            Dim this As T = Nothing
            Dim name As String = Nothing
            name = base + Convert.ToString(i)
            While (Not findVariable Is Nothing AndAlso findVariable(name, this)) OrElse _
                  (Not finder Is Nothing AndAlso finder.find(Me, name, this))
                findVariablesImpl(func, name, this, obj)
                i += 1
                name = base + Convert.ToString(i)
            End While
            Return i > start
        Else
            Return False
        End If
    End Function

    Public Function findVariables(Of T)(ByVal func As findVariablesCallback(Of T), _
                                        ByVal finder As iVariableFinder(Of T), _
                                        Optional ByVal base As String = Nothing, _
                                        Optional ByVal start As Int64 = 0, _
                                        Optional ByRef obj As Object = Nothing) As Boolean
        Return findVariables(func, Nothing, finder, base, start, obj)
    End Function

    Public Function findVariables(Of T)(ByVal func As findVariablesCallback(Of T), _
                                        ByVal finder As findVariableDelegate(Of T), _
                                        Optional ByVal base As String = Nothing, _
                                        Optional ByVal start As Int64 = 0, _
                                        Optional ByRef obj As Object = Nothing) As Boolean
        Return findVariables(func, finder, Nothing, base, start, obj)
    End Function

    Private Function iterateVariablesImpl(ByVal func As findVariablesCallback(Of bare_variable), _
                                          ByVal name As String, ByVal var As bare_variable, _
                                          ByRef obj As Object) As Boolean
        Return findVariablesImpl(func, name, var, obj)
    End Function

    Public Function iterateVariables(ByVal func As findVariablesCallback(Of bare_variable), _
                                     Optional ByVal filter As String = Nothing, _
                                     Optional ByRef obj As Object = Nothing) As Boolean
        If debugassert(Not func Is Nothing, "func is nothing.") Then
            Dim it As variables_t.iterator = Nothing
            it = variables.begin()
            While it <> variables.end()
                If filter Is Nothing OrElse fitfilter(filter, (+it).first(), True) Then
                    iterateVariablesImpl(func, (+it).first(), (+it).second, obj)
                End If
                it += 1
            End While
            Return True
        Else
            Return False
        End If
    End Function

    Private Shared Function findFunction(ByVal name As String, ByRef func As [function], _
                                         ByVal fs As functions_t) As Boolean
        assert(Not fs Is Nothing, "fs is nothing.")
        Dim it As functions_t.iterator = Nothing
        it = fs.find(name)
        If it = fs.end() Then
            Return False
        Else
            func = (+it).second
            Return True
        End If
    End Function

    Protected Function findContextFunction(ByVal name As String, ByRef func As [function]) As Boolean
        Return findFunction(name, func, functions)
    End Function

    Protected Shared Function findSharedFunction(ByVal name As String, ByRef func As [function]) As Boolean
        Return sharedContext.findFunction(name, func)
    End Function

    Public Overridable Function findFunction(ByVal name As String, ByRef func As [function]) As Boolean
        Return findContextFunction(name, func) OrElse findSharedFunction(name, func)
    End Function

    Public Function findFunction(ByVal name As String) As [function]
        Dim rtn As [function] = Nothing
        If findFunction(name, rtn) Then
            Return rtn
        Else
            Return Nothing
        End If
    End Function

    Private Shared Function cs() As stack(Of pair(Of [function], sentence))
        If _cs Is Nothing Then
            _cs = New stack(Of pair(Of [function], sentence))()
        End If

        Return _cs
    End Function

    Private Function invokeImpl(ByVal func As [function], ByRef rtn As bare_variable, _
                                ByVal sentence As sentence) As Boolean
        assert(Not func Is Nothing, "func is nothing.")
        Dim rst As Boolean = False
        _currentContext = Me
        cs().push(make_pair(func, sentence))
        Try
            rst = func.invoke(Me, rtn)
        Catch ex As Threading.ThreadAbortException
            rst = True
        Catch ex As Exception
            raiseError("unhandled exception caught when invoking function " + _
                       func.name() + ", ex " + ex.Message + ", callstack " + ex.StackTrace, _
                       errorHandle.errorType.exclamation)
            rst = False
        End Try

        cs().pop()
        Return rst
    End Function

    Private Shared Sub parameters_assert(ByVal p As iParameters, _
                                         ByVal p2 As iParametersBetweenContext, _
                                         ByVal p3 As iParametersWithMapping, _
                                         ByVal p4 As iParametersBetweenContextWithMapping, _
                                         ByVal msg As String)
        assert((p Is Nothing AndAlso p2 Is Nothing AndAlso p3 Is Nothing) OrElse _
               (p Is Nothing AndAlso p2 Is Nothing AndAlso p4 Is Nothing) OrElse _
               (p Is Nothing AndAlso p3 Is Nothing AndAlso p4 Is Nothing) OrElse _
               (p2 Is Nothing AndAlso p3 Is Nothing AndAlso p4 Is Nothing), _
               msg)
    End Sub

    Private Function invokeParameters(ByVal p As iParameters, _
                                      ByVal p2 As iParametersBetweenContext, _
                                      ByVal p3 As iParametersWithMapping, _
                                      ByVal p4 As iParametersBetweenContextWithMapping, _
                                      ByVal f As [function], _
                                      ByVal destctx As context, _
                                      ByVal srcctx As context) As Boolean
        If isdebugmode() Then
            parameters_assert(p, p2, p3, p4, _
                              "should at most have one parameter input to invokeParameters.")
        End If

        If Not p Is Nothing Then
            Return p.invoke(destctx)
        ElseIf Not p2 Is Nothing Then
            Return p2.invoke(destctx, srcctx)
        ElseIf Not p3 Is Nothing Then
            Return p3.invoke(destctx, f.mapping())
        ElseIf Not p4 Is Nothing Then
            Return p4.invoke(destctx, srcctx, f.mapping())
        Else
            Return True
        End If
    End Function

    Private Shared Function _clear(ByVal ctx As context) As Boolean
        ctx.clear()
        Return True
    End Function

    Private Function invokeImpl(ByVal f As [function],
                                ByVal p As iParameters,
                                ByVal p2 As iParametersBetweenContext,
                                ByVal p3 As iParametersWithMapping,
                                ByVal p4 As iParametersBetweenContextWithMapping,
                                ByRef rtn As bare_variable,
                                ByVal sentence As sentence) As Boolean
        assert(Not f Is Nothing, "function is nothing.")
        parameters_assert(p, p2, p3, p4, _
                          "should at most have one parameter input to invokeImpl.")

        Dim destctx As context = Nothing
        Dim index As Int64 = iContextpool.invalidIndex
        If p2 Is Nothing AndAlso p4 Is Nothing Then
            destctx = Me
        Else
            If Not contextpool().getfree(index, destctx) Then
                raiseError("do not have free context in contextpool.", errorHandle.errorType.exclamation)
                Return False
            Else
                If isdebugmode() Then
                    assert(destctx.functions.empty())
                    assert(destctx.variables.empty())
                End If
                copy(destctx.functions, functions)
                destctx._parent = Me
            End If
        End If

        Dim rst As Boolean = True
        If Not invokeParameters(p, p2, p3, p4, f, destctx, Me) Then
            raiseError("cannot invoke p/p2/p3/p4, ignore.", _
                       errorHandle.errorType.exclamation)
            rst = False
        Else
            rst = destctx.invokeImpl(f, rtn, sentence)
        End If

        If index <> iContextpool.invalidIndex AndAlso _
           (Not (_clear(destctx) And contextpool().release(index))) Then
            raiseError("cannot release context instance, index = " + Convert.ToString(index) + _
                       ", may cause memory leak.", errorHandle.errorType.exclamation)
        End If
        Return rst
    End Function

    Private Function invokeImpl(ByVal startFunctionName As String, _
                                ByVal p As iParameters, _
                                ByVal p2 As iParametersBetweenContext, _
                                ByVal p3 As iParametersWithMapping, _
                                ByVal p4 As iParametersBetweenContextWithMapping, _
                                ByRef rtn As bare_variable, _
                                ByVal sentence As sentence, _
                                ByRef f As [function]) As Boolean
        f = findFunction(startFunctionName)
        If f Is Nothing Then
            raiseError("expect function " + startFunctionName, errorHandle.errorType.user)
            Return False
        Else
            Return invokeImpl(f, p, p2, p3, p4, rtn, sentence)
        End If
    End Function

    Public Function invoke(ByVal startFunctionName As String, _
                           ByVal p As iParameters, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing, _
                           Optional ByRef f As [function] = Nothing) As Boolean
        Return invokeImpl(startFunctionName, p, Nothing, Nothing, Nothing, rtn, sentence, f)
    End Function

    Public Function invoke(ByVal startFunctionName As String, _
                           ByVal p As iParametersBetweenContext, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing, _
                           Optional ByRef f As [function] = Nothing) As Boolean
        Return invokeImpl(startFunctionName, Nothing, p, Nothing, Nothing, rtn, sentence, f)
    End Function

    Public Function invoke(ByVal startFunctionName As String, _
                           ByVal p As iParametersWithMapping, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing, _
                           Optional ByRef f As [function] = Nothing) As Boolean
        Return invokeImpl(startFunctionName, Nothing, Nothing, p, Nothing, rtn, sentence, f)
    End Function

    Public Function invoke(ByVal startFunctionName As String, _
                           ByVal p As iParametersBetweenContextWithMapping, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing, _
                           Optional ByRef f As [function] = Nothing) As Boolean
        Return invokeImpl(startFunctionName, Nothing, Nothing, Nothing, p, rtn, sentence, f)
    End Function

    Public Function invoke(ByVal startFunctionName As String, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing, _
                           Optional ByRef f As [function] = Nothing) As Boolean
        Return invokeImpl(startFunctionName, Nothing, Nothing, Nothing, Nothing, rtn, sentence, f)
    End Function

    Public Function invoke(Of T)(ByVal startFunctionName As String, _
                                 ByVal p As T, _
                                 Optional ByRef rtn As bare_variable = Nothing, _
                                 Optional ByVal sentence As sentence = Nothing,
                                 Optional ByRef f As [function] = Nothing) As Boolean
        If p Is Nothing Then
            Return invoke(startFunctionName, rtn, sentence, f)
        ElseIf istype(Of iParametersBetweenContextWithMapping, T)(p) Then
            Return invoke(startFunctionName,
                          DirectCast(p, iParametersBetweenContextWithMapping),
                          rtn,
                          sentence,
                          f)
        ElseIf istype(Of iParametersWithMapping, T)(p) Then
            Return invoke(startFunctionName,
                          DirectCast(p, iParametersWithMapping),
                          rtn,
                          sentence,
                          f)
        ElseIf istype(Of iParametersBetweenContext, T)(p) Then
            Return invoke(startFunctionName,
                          DirectCast(p, iParametersBetweenContext),
                          rtn,
                          sentence,
                          f)
        ElseIf istype(Of iParameters, T)(p) Then
            Return invoke(startFunctionName,
                          DirectCast(p, iParameters),
                          rtn,
                          sentence,
                          f)
        Else
            Return assert(False)
        End If
    End Function

    Public Function invoke(ByVal f As [function], _
                           ByVal p As iParameters, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing) As Boolean
        Return invokeImpl(f, p, Nothing, Nothing, Nothing, rtn, sentence)
    End Function

    Public Function invoke(ByVal f As [function], _
                           ByVal p As iParametersBetweenContext, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing) As Boolean
        Return invokeImpl(f, Nothing, p, Nothing, Nothing, rtn, sentence)
    End Function

    Public Function invoke(ByVal f As [function], _
                           ByVal p As iParametersWithMapping, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing) As Boolean
        Return invokeImpl(f, Nothing, Nothing, p, Nothing, rtn, sentence)
    End Function

    Public Function invoke(ByVal f As [function], _
                           ByVal p As iParametersBetweenContextWithMapping, _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing) As Boolean
        Return invokeImpl(f, Nothing, Nothing, Nothing, p, rtn, sentence)
    End Function

    Public Function invoke(ByVal f As [function], _
                           Optional ByRef rtn As bare_variable = Nothing, _
                           Optional ByVal sentence As sentence = Nothing) As Boolean
        Return invokeImpl(f, Nothing, Nothing, Nothing, Nothing, rtn, sentence)
    End Function

    Public Function invoke(Of T)(ByVal f As [function], _
                                 ByVal p As T, _
                                 Optional ByRef rtn As bare_variable = Nothing, _
                                 Optional ByVal sentence As sentence = Nothing) As Boolean
        If p Is Nothing Then
            Return invoke(f, rtn, sentence)
        ElseIf istype(Of iParametersBetweenContextWithMapping, T)(p) Then
            Return invoke(f, DirectCast(p, iParametersBetweenContextWithMapping), rtn, sentence)
        ElseIf istype(Of iParametersWithMapping, T)(p) Then
            Return invoke(f, DirectCast(p, iParametersWithMapping), rtn, sentence)
        ElseIf istype(Of iParametersBetweenContext, T)(p) Then
            Return invoke(f, DirectCast(p, iParametersBetweenContext), rtn, sentence)
        ElseIf istype(Of iParameters, T)(p) Then
            Return invoke(f, DirectCast(p, iParameters), rtn, sentence)
        Else
            Return assert(False)
        End If
    End Function

    Public Function Clone() As Object Implements ICloneable.Clone
        Dim rtn As context = Nothing
        rtn = alloc(Me)
        copy(rtn.variables, variables)
        copy(rtn.functions, functions)

        Return rtn
    End Function

    Public Sub clear()
        variables.clear()
        functions.clear()
    End Sub

    Public Shared Function callingcode(ByVal jump As Int64) As String
        If jump = 0 Then
            Return callingcode()
        Else
            Dim _cs As stack(Of pair(Of [function], sentence)) = Nothing
            copy(_cs, cs())
            Dim i As Int64 = 0
            While Not _cs.empty() AndAlso i < jump
                _cs.pop()
                i += 1
            End While
            If Not _cs.empty() Then
                Return callingcode(_cs.back())
            Else
                Return callingcode(convertor.cast(Of pair(Of [function], sentence))(Nothing))
            End If
        End If
    End Function

    Public Shared Function callstack() As String
        Dim _cs As stack(Of pair(Of [function], sentence)) = Nothing
        copy(_cs, cs())
        Dim rtn As StringBuilder = Nothing
        rtn = New StringBuilder()
        While Not _cs.empty()
            Dim caller As pair(Of [function], sentence) = Nothing
            caller = _cs.back()
            _cs.pop()
            rtn.Append(callingcode(caller))
            rtn.Append(character.newline)
        End While

        Return Convert.ToString(rtn)
    End Function

    Public Shared Function callingcode() As String
        Return callingcode(cs().back())
    End Function

    Private Shared Function scriptAll(ByVal i As iScript) As String
        If i Is Nothing Then
            Return "#NO_SCRIPTALL#"
        Else
            Return i.scriptAll()
        End If
    End Function

    Public Shared Function callingcode(ByVal this As pair(Of [function], sentence)) As String
        If this Is Nothing Then
            Return "#CANNOT_TRACE#"
        Else
            Return scriptAll(this.first) + " ^ " + scriptAll(this.second)
        End If
    End Function
End Class

'let it works just the same as a normal context, but set everything meanwhile into shared,
'to avoid some huge logic to fail into sharedContext
Public Class sharedContext_t
    Inherits context

    Public Overrides Function findFunction(ByVal name As String, ByRef func As [function]) As Boolean
        Return findContextFunction(name, func)
    End Function

    Public Overrides Function findVariable(ByVal name As String, ByRef o As bare_variable) As Boolean
        Return findContextVariable(name, o)
    End Function

    Public Overrides Function insertVariable(ByVal name As String, ByVal bv As bare_variable) As variables_t.iterator
        Return MyBase.insertVariable(name, New const_bare_variable(bv))
    End Function

    Public Overloads Function insertVariable(ByVal name As String, _
                                             ByVal type As typeDefination, _
                                             ByVal value As Object) As variables_t.iterator
        Return MyBase.insertVariable(name, New const_bare_variable(type, value))
    End Function
End Class

Public Module _sharedContext
    Public sharedContext As sharedContext_t = Nothing

    Sub New()
        sharedContext = New sharedContext_t()
    End Sub
End Module
